﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using BTM_Client_Application.SupportClasses;
using Client_Server_Interface;

namespace BTM_Client_Application.RealTimeFilter
{
    /// <summary>
    /// Логика взаимодействия для FilterElementControl.xaml
    /// </summary>
    public partial class FilterElementControl : UserControl
    {
        private readonly string _title;
        private List<object> _variants;
        private readonly FilterElementType _elementType;
        private readonly Popup _popup;
        //private StringFilterElementControl _stringFilterElement;
        private IFilterElementControl _filterElement;
        private RealTimeFilterControl.FilterUpdatedDelegate _onFilterUpdated;
        private Brush _normalResetButtonBackgroundBrush;

        private FilterElementControl()
        {
            InitializeComponent();
            //_popup = new Popup {Style = FindResource("MyPopup") as Style};
            _popup = new Popup();
            _popup.AllowsTransparency = true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="title">Заголовок для раздела фильтра.</param>
        /// <param name="initializer">Инициализатор фильтра.</param>
        /// <param name="del">Будет вызываться при обновлении фильтра.</param>
        public FilterElementControl(string title, FilterElementInitializer initializer, RealTimeFilterControl.FilterUpdatedDelegate del = null)
            : this()
        {
            _title = title;
            _elementType = initializer.ElementType;
            if (_elementType == FilterElementType.StartTime)
            {
                TitleButton.Background = Res.StartTimeFilterBrush;
            }
            else if (_elementType == FilterElementType.EndTime)
            {
                TitleButton.Background = Res.EndTimeFilterBrush;
            }
            else if(_elementType == FilterElementType.StartAndEndTime)
            {
                TitleButton.Background = Res.StartTimeFilterBrush;
            }
            _variants = initializer.ElementVariants;
            _onFilterUpdated = del;
            InitControl();
        }

        private void InitControl()
        {
            //Title.Text = _title;
            VoidDelegate onFilterPressClose = () =>
                {
                    _popup.IsOpen = false;
                };

            TitleButton.Content = _title;

            _normalResetButtonBackgroundBrush = ResetButton.Background;

            _popup.MouseLeave += (sender, args) =>
                {
                    ((Popup) sender).IsOpen = false;
                };

            switch (_elementType)
            {
                case FilterElementType.StringListContains:
                    _filterElement = StringFilterElementControl.Create(_elementType, _title, On_FilterUpdated, _variants);
                    break;
                case FilterElementType.StringList:
                    _filterElement = StringFilterElementControl.Create(_elementType, _title, On_FilterUpdated, _variants);
                    break;
                case FilterElementType.StringContains:
                    _filterElement = StringFilterElementControl.Create(_elementType, _title, On_FilterUpdated);
                    break;
                case FilterElementType.StartTime:
                    _filterElement = new DateTimeFilterElementControl(_elementType, On_FilterUpdated, onFilterPressClose);
                    break;
                case FilterElementType.EndTime:
                    _filterElement = new DateTimeFilterElementControl(_elementType, On_FilterUpdated, onFilterPressClose);
                    break;
                case FilterElementType.StartAndEndTime:
                    _filterElement = new DateTimeFilterElementControl(_elementType, On_FilterUpdated, onFilterPressClose);
                    break;
                case FilterElementType.NoControl:
                    _filterElement = null;
                    break;
                case FilterElementType.Other:
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
            if(_filterElement != null)
                _popup.Child = _filterElement.GetElement();
        }

        public void SetFilterActiveValue(FilterElementType valuesType, List<object> values)
        {
            _filterElement.SetFilterActiveValues(valuesType, values);
        }

        public void ClearFilter()
        {
            if(_filterElement != null)
                _filterElement.Clear();
        }

        /// <summary>
        /// Проверить один элемент.
        /// </summary>
        /// <param name="elementToCheck">Элемент для проверки.</param>
        /// <returns></returns>
        public bool CheckElement(object elementToCheck)
        {
            if (_filterElement == null)
                return true;
            return _filterElement.CheckElement(elementToCheck);
        }

        /// <summary>
        /// Получить список доступных элементов из заданного списка.
        /// </summary>
        /// <param name="elementsToCheck">Список с элементами для проверки.</param>
        /// <returns></returns>
        public List<object> CheckElements(List<object> elementsToCheck)
        {
            var toRet = elementsToCheck.Where(CheckElement).ToList();
            return toRet;
        }

        /// <summary>
        /// Установить список разрешенных элементов.
        /// </summary>
        /// <param name="items">Список разрешенных элементов.</param>
        public void SetFilterItems(List<object> items)
        {
            _variants = items;
            _filterElement.SetFilterItems(items);
        }

        public void SetOnFilterUpdatedAction(RealTimeFilterControl.FilterUpdatedDelegate del)
        {
            _onFilterUpdated = del;
        }

        private void TitleButton_OnClick(object sender, RoutedEventArgs e)
        {
            ShowPopup();
        }

        void ShowPopup()
        {
            _popup.Placement = PlacementMode.Center;
            _popup.PlacementTarget = this;
            _popup.IsOpen = true;
        }

        private void ResetButton_OnClick(object sender, RoutedEventArgs e)
        {
            if (_filterElement == null)
                return;
            _filterElement.Clear();
            SetInactive();
        }

        /// <summary>
        /// Генерирует событие при изменении параметров фильтра.
        /// </summary>
        private void On_FilterUpdated()
        {
            if (_onFilterUpdated != null)
                _onFilterUpdated(this);
            SetActive();
        }

        void SetActive()
        {
            ResetButton.Background = Res.ResetButtonActiveBrush;
        }

        void SetInactive()
        {
            ResetButton.Background = _normalResetButtonBackgroundBrush;
        }

        public List<object> ForRequestString
        {
            get
            {
                if (_filterElement != null)
                    return _filterElement.ForRequestString;
                return new List<object>();
            }
        }

        public interface IFilterElementControl
        {
            /// <summary>
            /// Устанавливает выбранные элементы.
            /// </summary>
            /// <param name="valuesType">Тип элементов.</param>
            /// <param name="values">Устанавливаемые элементы.</param>
            void SetFilterActiveValues(FilterElementType valuesType, List<object> values);
            /// <summary>
            /// Устанавливает список доступных для выбора элементов.
            /// </summary>
            /// <param name="filterElemets">Список допустимых элементов.</param>
            void SetFilterItems(List<object> filterElemets);
            /// <summary>
            /// Проверяет, является ли элемент elementToCheck допустимым для фильтра.
            /// </summary>
            /// <param name="elementToCheck">Элемент для проверки.</param>
            /// <returns></returns>
            bool CheckElement(object elementToCheck);
            /// <summary>
            /// Очищает фильтр.
            /// </summary>
            void Clear();
            /// <summary>
            /// Получает элемент управления фильтром.
            /// </summary>
            /// <returns></returns>
            UIElement GetElement();
            /// <summary>
            /// Вызывается при обновлении фильтра.
            /// </summary>
            VoidDelegate OnFilterUpdated { get; set; }
            /// <summary>
            /// Используется для заполнения строки запроса журнала с сервера.
            /// </summary>
            List<object> ForRequestString { get; }
        }


        
    }
}
